package Jihe;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

/*
* Set接口
* 1.无序的（不保证顺序）
* 2.不允许重复元素，可以有null但只能有1个
* 实现的类有:Hashsed.TreeSet.LinkedHashSet
*
* 如果要排序，选择treeset
* 如果不用排序，也不用保证顺序,也不用去除重复对象 选择hashset
* 如果不用排序，要保证顺序就选择linkedhashset
*
*
*
*   */
public class SetDemo {
    public static void main(String[] args) {
//        hashSet();
//        TreeSet();
        linkedHashSet();
    }
    /*1.LinkedHashSet
    * 哈希表和链表的实现
    * 它的顺序是基于我们添加的元素的顺序---链表
    *
    * */
    private static void linkedHashSet(){
        LinkedHashSet<Cat> link= new LinkedHashSet();
        Cat c1 = new Cat("米米","公",9);
        Cat c2 = new Cat("miaomiao","5",3);
        Cat c3 = new Cat("菊菊","公",2);
        Cat c4 = new Cat("miaomiao","4",2);
        link.add(c1);
        link.add(c2);
        link.add(c3);
        link.add(c4);
        for(Cat c:link){
            System.out.println(c);
        }

    }

    /*
    *2.TreeSet
    *有序的排序，String类型已经重写了排序算法
    * 基于TreeMap（二叉树），对象需要比较大小，通过对象比较器实现
    * 对象比较器可以进行排序，还能用来去除重复元素，如果自定义的数据类，没有实现比较器接口，将无法添加到TreeSet集合中
    * */
    private static void TreeSet(){
        TreeSet<Cat> tree = new TreeSet<Cat>();
        Cat c1 = new Cat("米米","公",9);
        Cat c2 = new Cat("miaomiao","5",3);
        Cat c3 = new Cat("菊菊","公",7);
        Cat c4 = new Cat("miaomiao","4",2);
        tree.add(c1);
        tree.add(c2);
        tree.add(c3);
        tree.add(c4);
        System.out.println(tree.size());
        for(Cat s:tree){
            System.out.println(s);
        }

    }
    /*
    * 3.HashSet
    * 1.实现原理,基于哈希表(HashMap)实现
    * 2.不允许重复元素,可以有一个null元素
    * 3.顺序是不保证恒久不变
    * 4.添加元素时,把元素作为HashMap的key存储,
    * HashMap的value使用一个固定的Object对象
    * 5.如何排除重复问题?
    * 排除重复元素是通过equals来检查对象是否相同.
    * 6.判断两个对象是否相同，先判断两个对象的hashcode是否相同：
    *   int result = 1;
        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());
        return result;
    * hashcode算法如上，如果相同则继续比较equals值是否相同。
    * 如果equals也相同，则就是同一个对象
    *
    * 小结：
    * （1）哈希表的存储结构：数组+链表，数组里的每一个元素以链表的形式存储
    * （2）如何把对象存储在哈希表中，先计算对象的hashcode值，然后对数组的长度取余数，来决定对想要存储在哪一个位置
    * （3）解决hashSet中的重复值使用的方式是：参考第6点
    *
    * */
     private static void hashSet(){
//        Set<String> set = new HashSet<>();
//        set.add("亮亮");
//        set.add("刘备");
//        set.add("张飞");
//        set.add("孙权");
//        set.add("羽羽");
//        set.add("羽羽");
//        String[] names = set.toArray(new String[]{});
//        for(String s:names){
//            System.out.println(s.toString());
//        }
//         System.out.println(set.size());
        Cat c1 = new Cat("米米","公",4);
        Cat c2 = new Cat("miaomiao","5",1);
        Cat c3 = new Cat("菊菊","公",5);
        Cat c4 = new Cat("miaomiao","5",1);
        Set<Cat> set1 = new HashSet<>();
        set1.add(c1);
        set1.add(c2);
        set1.add(c3);
        set1.add(c4);
        set1.add(c4);
//         System.out.println(c2.equals(c4));
//        System.out.println(set1.size());
         System.out.println(c4.hashCode());
         System.out.println(c2.hashCode());
         System.out.println(c1.hashCode());
         System.out.println(c3.hashCode());



    }
}
